package com.fx.zmlzml.filter;

import cn.hutool.core.exceptions.ValidateException;
import cn.hutool.json.JSONObject;
import cn.hutool.jwt.JWTUtil;
import cn.hutool.jwt.JWTValidator;
import com.fx.zmlzml.common.response.Result;
import com.fx.zmlzml.constant.SysConstants;
import com.fx.zmlzml.domain.dto.SysUserDetailDTO;
import com.fx.zmlzml.util.RedisUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;

@Component
public class JwtTokenFilter extends OncePerRequestFilter {

    @Autowired
    private RedisUtil redisUtil;
    
    @Autowired
    private ObjectMapper objectMapper;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        // 获取请求头中的token
        String token = request.getHeader("token");
        // 检查token是否为空
        if (token == null || token.isEmpty()) {
            // 如果token为空，直接放行
            filterChain.doFilter(request, response);
            return;
        }

        // 验证token5
        Result<SysUserDetailDTO> result = validateToken(token);
        if (result.getCode() != 200) {
            // 如果token验证失败，返回错误响应
            response.setContentType("application/json;charset=UTF-8");
            response.getWriter().write(objectMapper.writeValueAsString(Result.error(HttpServletResponse.SC_UNAUTHORIZED, result.getMsg())));
            return;
        }
        // 从token中提取用户信息
        SysUserDetailDTO sysUser = result.getData();

        SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken(sysUser, null, sysUser.getAuthorities()));

        // 如果token验证成功，继续处理请求
        filterChain.doFilter(request, response);
    }

    /**
     * 验证并解析 Token
     */
    public Result<SysUserDetailDTO> validateToken(String token) {
        try {
            // 1. 验证签名
            if (!JWTUtil.verify(token, SysConstants.SECRET_KEY.getBytes())) {
                return Result.error("签名无效");
            }

            // 2. 验证时间（过期时间等）
            JWTValidator.of(token).validateDate();

            // 3. 提取用户信息
            JSONObject tokenJson = JWTUtil.parseToken(token).getPayloads();
            // 从 Redis 中获取用户信息
            Long userId = tokenJson.getLong("userId");
            if (userId == null) {
                return Result.error("用户不存在");
            }

            SysUserDetailDTO userDetailDTO = (SysUserDetailDTO) redisUtil.getObject(SysConstants.LOGIN_TOKEN_PREFIX + userId, SysUserDetailDTO.class);
            if (userDetailDTO == null) {
                return Result.error("用户不存在");
            }
            return Result.success(userDetailDTO);

        } catch (ValidateException e) {
            return Result.error("Token 已过期");
        } catch (Exception e) {
            e.printStackTrace();
            return Result.error("Token验证失败: " + e.getMessage());
        }
    }

}